package it.eg.managedcor.impl;

import it.eg.managedcor.exceptions.TaskExecutionException;
import it.eg.managedcor.interfaces.ProcessInput;
import it.eg.managedcor.interfaces.ProcessOutput;
import it.eg.managedcor.interfaces.ProcessSessionData;
import it.eg.managedcor.interfaces.Task;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * This is a basic executor. It will execute all the tasks
 * provided in its constructor in the order 
 * provided.  
 * 
 * @see it.eg.managedcor.impl.TaskExecutionResult
 * 
 * @author Emanuele Gherardini
 *
 * @param <S> class implementing the {@link it.eg.managedcor.interfaces.ProcessSessionData} interface
 * @param <T> class implementing the {@link it.eg.managedcor.interfaces.Task} interface
 */
@SuppressWarnings("serial")
public abstract class AbstractTaskExecutor<S extends ProcessSessionData<? extends ProcessInput, ? extends ProcessOutput>, T extends Task<S>> implements java.io.Serializable {

	private static final Logger log = Logger.getLogger(AbstractTaskExecutor.class);
	
	protected final List<T> tasksToBeExecuted;
	protected final S sessionData;
	
	/**
	 * Construct an <code>AbstractTaskExecutor</code> with no already
	 * executed tasks
	 * 
	 * @param tasksToBeExecuted
	 * @param sessionData
	 */
	public AbstractTaskExecutor(List<T> tasksToBeExecuted, S sessionData) {
		
		this.tasksToBeExecuted = new ArrayList<T>(tasksToBeExecuted.size());
		this.tasksToBeExecuted.addAll(tasksToBeExecuted);
		
		this.sessionData = sessionData;
		
	}
	

	
	public void executeTasks() throws TaskExecutionException {

		log.debug("executeTasks() - BEGIN");
		
		Iterator<T> taskIterator = tasksToBeExecuted.iterator();
		
		while(taskIterator.hasNext()) {
			
			T task = taskIterator.next();
			
			TaskExecutionResult taskExecutionResult;
			
			taskExecutionResult = task.performTask(sessionData);
			
			log.info("executeTasks() - Task: " + task + " executed. Result: " + taskExecutionResult);
			
			if(taskExecutionResult.isPerformed()) {
				taskIterator.remove();
			}
			
			if(taskExecutionResult.isStop()) {
				break;
			}
			
		}
		
		log.debug("executeTasks() - END");
		
	}
	
	
}

